//   Copyright 2012,2013 Vaughn Vernon
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
package com.saasovation.identityaccess.application;

import com.saasovation.common.annotation.TestContainers;
import com.saasovation.common.domain.model.DomainEventPublisher;
import com.saasovation.common.event.EventStore;
import com.saasovation.identityaccess.IdentityAccessAppTest;
import com.saasovation.common.TestBase;
import com.saasovation.identityaccess.domain.model.DomainRegistry;
import com.saasovation.identityaccess.domain.model.access.Role;
import com.saasovation.identityaccess.domain.model.identity.*;
import org.junit.jupiter.api.BeforeEach;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.springframework.transaction.annotation.Transactional;

import java.util.UUID;

@SpringBootTest(classes = IdentityAccessAppTest.class)
@TestContainers(use = true)
@Transactional
public abstract class ApplicationServiceTestBase extends TestBase {
    protected static final String FIXTURE_GROUP_NAME = "Test Group";
    protected static final String FIXTURE_PASSWORD = "SecretPassword!";
    protected static final String FIXTURE_ROLE_NAME = "Test Role";
    protected static final String FIXTURE_TENANT_DESCRIPTION = "This is a test tenant.";
    protected static final String FIXTURE_TENANT_NAME = "Test Tenant";
    protected static final String FIXTURE_USER_EMAIL_ADDRESS = "jdoe@saasovation.com";
    protected static final String FIXTURE_USER_EMAIL_ADDRESS2 = "zdoe@saasovation.com";
    protected static final String FIXTURE_USERNAME = "jdoe";
    protected static final String FIXTURE_USERNAME2 = "zdoe";


    @DynamicPropertySource
    public static void dataSourceProperties(DynamicPropertyRegistry registry) {
        if (!useTestContainers(ApplicationServiceTestBase.class)) {
            return;
        }
        initMySqlContainer(registry);
        initRabbitMqContainer(registry);
    }

    @Autowired
    protected EventStore eventStore;

    public ApplicationServiceTestBase() {
        super();
    }

    @BeforeEach
    public void beforeEach() {
        DomainEventPublisher.instance().reset();
    }

    protected Tenant tenantAggregate() {
        return DomainRegistry.tenantProvisioningService()
                .provisionTenant(FIXTURE_TENANT_NAME + ":" + UUID.randomUUID(),
                        FIXTURE_TENANT_DESCRIPTION,
                        new FullName("John", "Doe"),
                        new EmailAddress(FIXTURE_USER_EMAIL_ADDRESS),
                        new PostalAddress(
                                "123 Pearl Street",
                                "Boulder",
                                "CO",
                                "80301",
                                "US"),
                        new Telephone("303-555-1210"),
                        new Telephone("303-555-1212"));
    }

    protected Group groupAggregate(Tenant tenant) {
        return tenant.provisionGroup(FIXTURE_GROUP_NAME + ":" + UUID.randomUUID(),
                "A test group 1.");
    }


    protected Role roleAggregate(Tenant tenant) {
        return tenant.provisionRole(FIXTURE_ROLE_NAME + ":" + UUID.randomUUID(),
                "A test role.", true);
    }

    protected User userAggregate(Tenant tenant) {
        RegistrationInvitation invitation =
                tenant.offerRegistrationInvitation("open-ended").openEnded();
        return tenant.registerUser(invitation.invitationId(),
                "jdoe" + ":" + UUID.randomUUID(),
                FIXTURE_PASSWORD,
                Enablement.indefiniteEnablement(),
                new Person(tenant.tenantId(),
                        new FullName("John", "Doe"),
                        new ContactInformation(new EmailAddress(FIXTURE_USER_EMAIL_ADDRESS),
                                new PostalAddress("123 Pearl Street",
                                        "Boulder",
                                        "CO",
                                        "80301",
                                        "US"),
                                new Telephone("303-555-1210"),
                                new Telephone("303-555-1212"))));
    }

}
